﻿#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//数组是一组相同类型元素的集合
//数组是使用下标来访问的，下标是从0开始的
//在C99之前，数组的大小必须是常量或者常量表达式
//在C99之后，数组的大小可以是变量（为了支持变长数组）
//下面这个代码只能在支持C99标准的编译器上编译
//int n = 10;
//scanf("%d",&n);
//int arr[n]; //这种数组不能初始化
int main()
{
	int arr[10] = { 0 };//不完全初始化，剩余元素默认初始化为0
	int arr1[10] = { 0,1,2,3,4,5,6,7,8,9 };//完全初始化
	int arr2[10] = { 0,1,2 };//括号里可以不填，只放了3个元素

	char ch1[10] = { 'a','b','c' };//a b c 0  0 0 0 0 0 0
	char ch2[10] = "abc";          //a b c \0 0 0 0 0 0 0 
	//ch1和ch2的结果是一样的
	char ch3[] = { 'a','b','c' };//括号里可以不填，只放了3个元素
	char ch4[] = "abc";//括号里可以不填，只放了4个元素
	//注意ch3和ch4的区别
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		printf("%c ", ch1[i]);
	}
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		printf("%c ", ch2[i]);
	}
	printf("\n");
	for (i = 0; i < 3; i++)
	{
		printf("%c ", ch3[i]);
	}
	printf("\n");
	for (i = 0; i < 4; i++)
	{
		printf("%c ", ch4[i]);
	}
	printf("\n");
	//如果要打印地址
	for (i = 0; i < 10; i++)
	{
		printf("&arr[%d] = %p\n", i, &arr[i]);
	}
	printf("\n");



	//二维数组
	//要输入下面这一堆数字可以建立二维数组
	//1 2 3 4
	//2 3 4 5
	//3 4 5 6
	//int arr3[3][4];第一个[]表示行，第二个[]表示列
	//怎样进行初始化呢？
	int arr3[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };//完全初始化可以像这样一口气将输进去
	int arr4[3][4] = { 1,2,3,4,2,3,4,5,3,4 };//如果不完全初始化，则后面自动添齐0
	int arr5[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };//完全初始化也可以像这样系那个同一行放在一个括号里
	int arr6[3][4] = { {1,2},{2,3},{3,4} };//如果像这样不完全初始化，则是每个括号自动添齐0，因为每行的元素个数是确定了的
	//行可以省，列不能生省
	int arr7[][4] = { 1,2,3,4,2,3,4,5,3,4 };//此处省略了行对比arr5和arr7，是一模一样的
	//int arr8[3][] = { 1,2,3,4,2,3,4,5,3,4 };此处省略了列就会造成歧义，由于自动补齐原则，这个地方可能是4列，5列，6列等等，所以列不能省

	//二维数组行与列的编号都和一维数组一样，从0开始的，如果要查找arr3中的第2行第3列的元素该如何找呢？注意，不是arr3[2][3],而是arr3[1][2]

	//如果要重新为arr3数组赋值
	int line = 0;
	for (line = 0; line < 3; line++)
	{
		int column = 0;
		for (column = 0; column < 4; column++)
		{
			scanf("%d", &arr3[line][column]);
		}
	}
	//如果要打印arr3数组则
	for (line = 0; line < 3; line++)
	{
		int column = 0;
		for (column = 0; column < 4; column++)
		{
			printf("%d ", arr3[line][column]);
		}
		printf("\n");
	}
	//二维数组有行和列，是一个矩阵的形式，那是不是二维数组在内存中也是这个形式呢？实际上在内存中的存储形式是一样的，是连续存放的
	for (line = 0; line < 3; line++)
	{
		int column = 0;
		for (column = 0; column < 4; column++)
		{
			printf("arr3[%d][%d] = %p\n", line, column, &arr3[line][column]);
		}
	}

	//二维数组可以看作是一维数组的数组，每一行看作是一个一维数组
	//还是以下面这个数组为例：
	//	1 2 3 4   arr[0][j]   第一行一维数组的数组名是arr[0]
	//	2 3 4 5   arr[1][j]   第二行一维数组的数组名是arr[1]
	//	3 4 5 6   arr[2][j]   第三行一维数组的数组名是arr[2]

	//数组要注意不要越界

	//数组名的意义
	//基本上所有的数组名都是首元素的首地址
	//但有两个例外：
	//1.sizeof(数组名），这里的数组名表示整个数组，计算的是整个数组的大小，单位是字节
	//2.&数组名，这里的数组名表示的是整个数组，去除的是整个数组的地址
	int arr8[10];
	printf("%p\n", arr);//首元素的首地址
	printf("%p\n", arr+1);//首元素的第二个地址
	printf("- - - - - - - - - - - - - \n");
	printf("%p\n", &arr[0]);//首元素的首地址
	printf("%p\n", &arr[0]+1);//首元素的第二个地址
	printf("- - - - - - - - - - - - - \n");
	printf("%p\n", &arr);//数组的地址------就是数组首元素的首地址
	printf("%p\n", &arr + 1);//整个数组结束之后的那个地址
	printf("- - - - - - - - - - - - - \n");
	int n = sizeof(arr);//整个数组的大小
	printf("%d\n", n);
	printf("- - - - - - - - - - - - - \n");

	//二维数组数组名
	int arr9[3][4] = { 0 };
	printf("%d\n",sizeof(arr9[0][0]));//计算一个元素的大小
	printf("%d\n",sizeof(arr9[0]));//计算一行的大小
	printf("%d\n", sizeof(arr9));//计算整个数组的大小
	printf("%d\n", sizeof(arr9) / sizeof(arr9[0]));//计算一共有多少行：数组的大小/每一行的大小（每一行的数组名表示）
	printf("%d\n",sizeof(arr9)[0] / sizeof(arr9[0][0]));//计算一共有多少列：每一行的大小（每一行的数组名表示）/每一个元素的大小













	return 0;
}























